package it.mouseclient;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.io.Serializable;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

import common.Command;
import common.CommandType;

public class UDPClient implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -3550433832269571589L;
	private DatagramSocket clientSocket;
	private byte[] sendData = new byte[1024];
	private byte[] receiveData = new byte[1024];

	private InetAddress serverAddress;
	private int port;
	private final static int CONNECTION_TIMEOUT = 5000;
	private String connectionKey;

	public UDPClient(InetAddress address, int port) {
		serverAddress = address;
		this.port = port;
		connectionKey = "";
	}

	public void open() throws IOException {

		clientSocket = new DatagramSocket();
		// imposto il timeout per la lettura del flusso da parte del server
		// (ObjectInputStream)
		clientSocket.setSoTimeout(CONNECTION_TIMEOUT);

	}

	public void close(boolean disconnect) {
		if (disconnect)
			executeCommand(CommandType.DISCONNECT, null);

		if (clientSocket != null) {
			clientSocket.close();
			clientSocket = null;
		}
	}

	public synchronized boolean executeCommand(CommandType type, String value) {
		if (clientSocket != null) {
			try {
				Command c = new Command(type, value, connectionKey);
				clientSocket.send(createDatagram(c));
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			}
			return true;
		}
		return false;
	}

	private DatagramPacket createDatagram(Command c) throws IOException {
		ByteArrayOutputStream bStream = new ByteArrayOutputStream();
		ObjectOutput oo = new ObjectOutputStream(bStream);
		oo.writeObject(c);
		oo.close();
		sendData = bStream.toByteArray();
		bStream.close();

		DatagramPacket sendPacket = new DatagramPacket(sendData,
				sendData.length, serverAddress, port);
		return sendPacket;
	}

	public boolean isConnected() {
		boolean conn = false;
		if (clientSocket != null)
			conn = clientSocket.isConnected();
		return conn;

	}

	public boolean doLogin(String password) {
		boolean logged = false;
		if (clientSocket != null) {
			try {
				connectionKey = password;

				// invio password al server (richiesta login)
				executeCommand(CommandType.LOGIN, "");
				// attendo conferma login
				DatagramPacket receivePacket = new DatagramPacket(receiveData,
						receiveData.length);
				clientSocket.receive(receivePacket);
				ObjectInputStream iStream = new ObjectInputStream(
						new ByteArrayInputStream(receivePacket.getData()));
				Command received = (Command) iStream.readObject();
				iStream.close();
				if (received.getType().equals(CommandType.LOGIN)
						&& Boolean.parseBoolean(received.getValue())) {
					logged = true;

				}

			} catch (OptionalDataException e) {
				e.printStackTrace();
				logged = false;

			} catch (ClassNotFoundException e) {
				e.printStackTrace();
				logged = false;

			} catch (IOException e) {
				e.printStackTrace();
				logged = false;
			}

		}
		return logged;
	}
}
